/*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.javlov.vf;

import java.io.Serializable;

import net.javlov.State;

public interface ValueFunction<T> extends Serializable {
	
	/**
	 * Returns the value of the state s; returns an initial value if the state is not
	 * currently known.
	 * 
	 * @param s the state for which to get the value
	 * @return value of s if it is known, or an initial value if it is not
	 */
	double getValue(State<? extends T> s);
	
	/**
	 * Returns the value of the state s; returns null if the state is not
	 * currently known (for table-based methods; for function approximators, the
	 * return value will be the same as for {@link #getValue(State)}).
	 * 
	 * @param s the state for which to get the value
	 * @return value of s if it is known, or null if it is not
	 */
	Double queryValue(State<? extends T> s);
	
	/**
	 * Initialize the function (e.g. at beginning of run).
	 */
	void init();
	
	/**
	 * Reset the function (e.g. in between episodes).
	 */
	void reset();
	
	/**
	 * Set the value of state s to the specified value. Generally, only table-based
	 * value functions will be able to exactly reproduce the value. Approximators
	 * should move towards the specified value.
	 * 
	 * @param s the state
	 * @param value the value that the state should have
	 */
	void setValue(State<? extends T> s, double value);
	
	/**
	 * Update the value of state s with the specified delta; that is, add the delta
	 * to the current value of s (for table-based functions), or update the weights
	 * with the gradient of the function multiplied by delta (for function approximators).
	 * 
	 * @param s the state
	 * @param delta the value that should be added to the current value of the state
	 */
	void update(State<? extends T> s, double delta);
}
